package com.dcloud.flow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dcloud.core.dsplugin.IDsService;
import com.dcloud.flow.entity.AipFlow;
import com.dcloud.flow.entity.AipFlowNode;
import com.dcloud.flow.entity.request.GetFlowByTaskIdRequest;
import com.dcloud.flow.entity.request.SaveNodeFieldMapRequest;
import com.dcloud.flow.entity.request.SaveNodeValueRequest;
import com.dcloud.flow.entity.vo.NodeFieldMap;
import com.dcloud.flow.mapper.AipFlowMapper;
import com.dcloud.flow.mapper.AipFlowNodeMapper;
import com.dcloud.flow.service.IAipFlowService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @Description: aip_flow
 * @Author: jeecg-boot
 * @Date:   2023-07-28
 * @Version: V1.0
 */
@Service
public class AipFlowServiceImpl extends ServiceImpl<AipFlowMapper, AipFlow> implements IAipFlowService {

    String initConfig = "{\n" +
            "\t\"lineList\":[],\n" +
            "\t\"name\":\"初始化流程\",\n" +
            "\t\"nodeList\":[]\n" +
            "}";

    @Autowired
    AipFlowMapper aipFlowMapper;

    @Autowired
    AipFlowNodeMapper aipFlowNodeMapper;

    @Autowired
    IDsService iDsService;

    @Autowired
    ObjectMapper objectMapper;

    @Override
    public AipFlow getFlowByTaskId(GetFlowByTaskIdRequest getFlowByTaskIdRequest) {
        AipFlow aipFlow = aipFlowMapper.selectOne(new LambdaQueryWrapper<AipFlow>().eq(AipFlow::getTaskId, getFlowByTaskIdRequest.getTaskId()));
        if(aipFlow != null){
            return aipFlow;
        }else{
            //该任务如果没有绑定流程的话，就新建一个
            AipFlow newAipFlow = new AipFlow();
            newAipFlow.setVersion(String.valueOf(new Date().getTime()));
            newAipFlow.setTaskId(getFlowByTaskIdRequest.getTaskId());
            newAipFlow.setCreateTime(new Date());
            newAipFlow.setFollowConfig(initConfig);
            aipFlowMapper.insert(newAipFlow);
            return newAipFlow;
        }
    }

    /**
     * @Author shijf
     * @Description //流程节点保存
     * @Date 16:54 2023/8/8
     * @param saveNodeValueRequest
     **/
    @Override
    public void saveNode(SaveNodeValueRequest saveNodeValueRequest) {
        AipFlowNode aipFlowNode = new AipFlowNode();
        aipFlowNode.setFlowNodeId(saveNodeValueRequest.getFlowNodeId());
        aipFlowNode.setNodeConfigVal(saveNodeValueRequest.getNodeConfigValue());
        aipFlowNode.setCompCode(saveNodeValueRequest.getCompCode());
        aipFlowNode.setFlowId(saveNodeValueRequest.getFlowId());

        //如果已经存在，就修改流程节点配置，如果不存在就新增
        AipFlowNode aipFlowNodeExist = aipFlowNodeMapper.selectOne(new LambdaQueryWrapper<AipFlowNode>().eq(AipFlowNode::getFlowNodeId, saveNodeValueRequest.getFlowNodeId()));
        if(aipFlowNodeExist == null){
            aipFlowNodeMapper.insert(aipFlowNode);
        }else{
            aipFlowNodeMapper.update(aipFlowNode,new LambdaQueryWrapper<AipFlowNode>().eq(AipFlowNode::getFlowNodeId,saveNodeValueRequest.getFlowNodeId()));
        }

    }

    @Override
    public AipFlowNode getNodeByNodeId(SaveNodeValueRequest saveNodeValueRequest) {
        AipFlowNode aipFlowNode = aipFlowNodeMapper.selectOne(new LambdaQueryWrapper<AipFlowNode>().eq(AipFlowNode::getFlowNodeId, saveNodeValueRequest.getFlowNodeId()));
        return aipFlowNode;
    }

    /**
     * @param saveNodeValueRequest
     * @return
     * @Author shijf
     * @Description //根据节点id自动生成出入参数映射
     * @Date 16:54 2023/8/8
     */
    @Override
    public List<NodeFieldMap> genNodeParam(SaveNodeValueRequest saveNodeValueRequest) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        AipFlowNode node = this.getNodeByNodeId(saveNodeValueRequest);
        List<Map<String, Object>> maps = this.jxSelect(node);
        List<NodeFieldMap> list = new LinkedList<>();
        if (maps.size() > 0) {
            Map<String, Object> stringObjectMap = maps.get(0);
            stringObjectMap.forEach((key, value) -> {
                NodeFieldMap nodeFieldMap = new NodeFieldMap();
                nodeFieldMap.setInputField(key);
                nodeFieldMap.setOutputField(key);
                list.add(nodeFieldMap);
            });
        }

        return list;
    }

    @Override
    public void saveNodeFieldMap(SaveNodeFieldMapRequest saveNodeFieldMapRequest) throws JsonProcessingException {
        AipFlowNode aipFlowNode = new AipFlowNode();
        aipFlowNode.setFlowNodeId(saveNodeFieldMapRequest.getFlowNodeId());
        aipFlowNode.setFieldMap(objectMapper.writeValueAsString(saveNodeFieldMapRequest.getFieldMaps()));
        aipFlowNodeMapper.update(aipFlowNode,new LambdaQueryWrapper<AipFlowNode>().eq(AipFlowNode::getFlowNodeId,saveNodeFieldMapRequest.getFlowNodeId()));
    }

    /**
     * @param node 节点数据
     * @return
     * @Author shijf
     * @Description //根据节点配置即席查询
     * @Date 16:54 2023/8/8
     */
    public List<Map<String, Object>> jxSelect(AipFlowNode node) {

        if(StringUtils.isEmpty(node.getNodeConfigVal())){
            return null;
        }
        String compCode = node.getCompCode(); //组件编码
        try {
            Map<String,String> map = objectMapper.readValue(node.getNodeConfigVal(), Map.class);
            String execSql = map.get("execSql");
            String dataSource = map.get("dataSource");
            List<Map<String, Object>> maps = iDsService.selectSqlBySourceId(execSql, Integer.valueOf(dataSource), 10l);
            return maps;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }


}
